/* ----------------------------------------------------------------------------
* File: game_controller.h
*
* Desc: Game controller for quiz functionality
*
* Created: 06/05/2011, by Alexey Korshunov
* ---------------------------------------------------------------------------- */
#ifndef _GAME_CONTROLLER_H_
#define _GAME_CONTROLLER_H_

#include <memory>
#include <atlbase.h>
#include <atlcom.h>

#include "debug_logger.h"
#include "dictionary.h"
#include "user_profile.h"
#include "exception.h"
#include "thread_wrapper.h"
#include "quiz_common.h"
#include "timer.h"
#include "utils.h"

namespace QuizCore
{	
	struct QuestionNotifyParams
	{
		QuestionNotifyParams()
			: answer_symbols(0)
		{
		}

		std::string question;
		unsigned int answer_symbols;
	};

	struct CorrectAnswerNotifyParams
	{
		CorrectAnswerNotifyParams()
			: points(0)
		{
		}

		std::string user;
		unsigned int points;
	};

	struct TimeoutNotifyParams
	{
		std::string answer;
	};

	struct PromptNotifyParams
	{
		std::string prompt;
	};

	struct QuestionDelayNotifyParams
	{
		QuestionDelayNotifyParams()
			: delay(0)
		{
		}
		unsigned int delay;	// sec
	};

	struct NextQuestionNotifyParams
	{
		std::string answer;
	};

	struct ControllerParams
	{
		ControllerParams()
			: DictManager(NULL)
			, ProfileManager(NULL)
			, Queue(NULL)
			, QuestionTimeout(0)
			, QuestionDelay(0)
			, AutoPrompts(false)
			, PromptTime(0)
		{
		}

		QuizCore::DictionaryManager* DictManager;
		QuizCore::UserProfileManager* ProfileManager;
		Common::Utils::ConcurrentQueue<MsgInfo>* Queue;
		unsigned int QuestionTimeout;	// in ms
		unsigned int QuestionDelay;		// in ms
		bool AutoPrompts;
		unsigned int PromptTime;		// in ms
	};

	class GameEventHandler
	{
	public:
		virtual ~GameEventHandler()
		{
		}

		virtual void QuestionDelayNotify(const QuestionDelayNotifyParams& params) = 0;
		virtual void QuestionNotify(const QuestionNotifyParams& params) = 0;
		virtual void CorrectAnswerNotify(const CorrectAnswerNotifyParams& params) = 0;
		virtual void TimeoutNotify(const TimeoutNotifyParams& params) = 0;
		virtual void PromptNotify(const PromptNotifyParams& params) = 0;
		virtual void NextQuestionNotify(const NextQuestionNotifyParams& params) = 0;
	};

	class GameController 
		: public Common::ThreadWrapper
	{
	public:
		GameController(GameEventHandler* handler, const ControllerParams& params) 
			throw(Common::Exception);
		~GameController();

		// ThreadWrapper implementation
		virtual Common::Error Run();

		Common::Error Start();
		Common::Error Stop();
		Common::Error GeneratePrompt();
		Common::Error NextQuestion();

	private:
		Common::Error CheckParams(const ControllerParams& params);
		Common::Error RunGame();
		Common::Error RunGameWithPrompts();
		std::auto_ptr<Common::Timer> CreatePromptTimer();
		std::auto_ptr<Common::Timer> CreateQuestionTimer();
		void ProcessNewQuestion(std::string& question);
		void CreatePrompt(std::string& prompt);
		bool CheckQueue(MsgInfo& info);

		static void TimeoutCallback(void* param);
		static void PromptTimeoutCallback(void* param);
		static void AnswerTimeoutCallback(void* param);

		GameEventHandler& m_EventHandler;
		ControllerParams m_Params;

		unsigned int m_CountQuestions;
		unsigned int m_CurNumQuestion;

		std::auto_ptr<Common::Logger> m_Logger;
		unsigned int m_CountPrompts;

		HANDLE m_PromptEvent;
		HANDLE m_AnswerTimeoutEvent;
		HANDLE m_PushQueueEvent;
		HANDLE m_NextQuestionEvent;
		CRITICAL_SECTION m_csAnswerLock;
		std::string m_Answer;
		bool m_GameStarted;
	};
}


#endif // _GAME_CONTROLLER_H_
